package Week10;

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.ArrayList;
import javax.imageio.ImageIO;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;




	//====================================================================================
	//GUI class
	//====================================================================================

	//An over-simplified GUI for drawing.
	@SuppressWarnings("serial") //Just to suppress a warning
	public class MapMainProg extends JPanel implements ActionListener, MouseListener, MouseMotionListener{

		//Member variables.
		private Point pnt;
		private ArrayList<Point> digList = new ArrayList<Point>();
		private ArrayList<POI> poiList = new ArrayList<POI>();
		private ArrayList<PolyLine> polyLineList = new ArrayList<PolyLine>();
		private ArrayList<Polygon> polygonList = new ArrayList<Polygon>();
		protected int userX, userY;
		private static BufferedImage campus;
		private int mouseX, mouseY;
		private String modeStatus = "off";
		private poiInOut op1 = new poiInOut(poiList);
		private polyLineInOut op2 = new polyLineInOut(polyLineList);
		private polygonInOut op3 = new polygonInOut(polygonList);
		private int curX=-1, curY=-1;
		private int poiIndex, polyLineIndex, polygonIndex, polyLinePoiIndex, polygonPoiIndex;
		private double polygonSnapDist = 20;  //setting a default snap distance, just in case
		private boolean inDrag = false;
		private int cursorStatus = 1;
		private String newFeatureName = null;
		private PolyLine currentPolyline = new PolyLine(null);
		private Polygon currentPolygon = new Polygon(null);
		final JFileChooser fc = new JFileChooser();
		float alpha = 0.50f;
		int type = AlphaComposite.SRC_OVER; 
		AlphaComposite composite = 
		AlphaComposite.getInstance(type, alpha);
		
		
		

		
		//Constructor for MapMainProg.
		public MapMainProg() {
			
			//Calls the constructor of JPanel to enable DoubleBuffering to avoid flickering.
			super(true); 
			
			//Set the (preferred) size of the panel			
			setPreferredSize(new Dimension(699,446));
		}
		


		
	//====================================================================================
	//ACTIONS (CONTROL)
	//====================================================================================


		//Multi-listener using if-statements dependent upon the menu item clicked.
		public void actionPerformed(ActionEvent arg0){

			if (arg0.getActionCommand() == "Polygon Closing Snap Distance"){ 
				
				String returnValue = (String) JOptionPane.showInputDialog(
						null,
						"Enter the Polygon Closing Snap Distance",
						"Polygon Closing Snap Distance",
						JOptionPane.PLAIN_MESSAGE,
						null,
						null,
						polygonSnapDist);

				if(returnValue == null || returnValue.isEmpty() || !returnValue.matches("\\d+([.]\\d)?")){
					JOptionPane.showMessageDialog(null, "Polygon Closing Snap Distance not changed: "+ polygonSnapDist);
				}
				else{
					polygonSnapDist = Double.parseDouble(returnValue);					
				}
								
				System.out.println("");
				System.out.println("Polygon closing snap distance: " + polygonSnapDist);
			}			
			
			//Actions for clicking "List all objects" button.
			if (arg0.getActionCommand() == "List all objects"){

				//Print to console.
				System.out.println("");
				System.out.println("====================");
				System.out.println("Listing all objects:");
				System.out.println("====================");
				
				System.out.println("");
				System.out.println("Number of POIs: " + poiList.size());				
				System.out.println("");
				System.out.println("POIs:");
				for (int i = 0; i < poiList.size(); i++){
						System.out.println(poiList.get(i).getPt() + "   " + poiList.get(i).getLabel());					
				}
				
				System.out.println("");
				System.out.println("--------------------");
				System.out.println("");
				System.out.println("Number of Polylines: " + polyLineList.size());				
				for (int i = 0; i < polyLineList.size(); i++){
					System.out.println("");
					System.out.println("Polyline #" + (i+1));
					System.out.println("Name: " + polyLineList.get(i).getLabel());
					for (int j = 0; j < polyLineList.get(i).getPolypoints().size(); j++){
						System.out.println(polyLineList.get(i).getPolypoints().get(j).getPt());
					}
				}
				
				System.out.println("");
				System.out.println("--------------------");
				System.out.println("");
				System.out.println("Number of Polygons: " + polygonList.size());				
				for (int i = 0; i < polygonList.size(); i++){
					System.out.println("");
					System.out.println("Polygon #" + (i+1));
					System.out.println("Name: " + polygonList.get(i).getLabel());
					for (int j = 0; j < polygonList.get(i).getPolypoints().size(); j++){
						System.out.println(polygonList.get(i).getPolypoints().get(j).getPt());
					}
				}
				System.out.println("");
				System.out.println("--------------------");

			}
			
			//Actions for clicking "Label POI or Vertex" menu item.
			//if (arg0.getActionCommand() == "Digitize Path"){
			if (arg0.getActionCommand() == "Label POI or Vertex"){

				//Print to console.
				System.out.println("");
				System.out.println("Switching modes ...");
				System.out.println("from: " + modeStatus);
	
				//Set status to "dig" (Digitize Path ... now Inquiry),
				//for use with overridden mouseRelease method.
				modeStatus = "dig";
				if (digList.size() > 0){
					ArrayList<Point> digList = new ArrayList<Point>();
					this.digList = digList;
				}			
				
				//Print to console.
				System.out.println("to: " + modeStatus);
								
				//Repaint the GUI.
				repaint();			
			}

			
			//Actions for clicking "Create/Move POIs" button.
			if (arg0.getActionCommand() == "Create/Move POIs"){
				
				//Print to console.
				System.out.println("");
				System.out.println("Switching modes ...");
				System.out.println("from: " + modeStatus);
				
				//Set status to "poi" (Enter Points of Interest),
				//for use with overridden mouseRelease method.
				modeStatus = "poi";
				newFeatureName = null;
				
				//Print to console.
				System.out.println("to: " + modeStatus);
		
				//Repaint the GUI.
				repaint();
			}
			
			//Actions for clicking "Create/Move Polyline Vertices" button.
			if (arg0.getActionCommand() == "Create/Move Polyline Vertices"){
				
				//Print to console.
				System.out.println("");
				System.out.println("Switching modes ...");
				System.out.println("from: " + modeStatus);
				
				//Set status to "poi" (Enter Points of Interest),
				//for use with overridden mouseRelease method.
				modeStatus = "PolyLine";
				newFeatureName = null;
				currentPolyline = new PolyLine(null);
				
				//Print to console.
				System.out.println("to: " + modeStatus);
		
				//Repaint the GUI.
				repaint();
			}

			//Actions for clicking "Create/Move Polygon Vertices" button.
			if (arg0.getActionCommand() == "Create/Move Polygon Vertices"){
				
				//Print to console.
				System.out.println("");
				System.out.println("Switching modes ...");
				System.out.println("from: " + modeStatus);
				
				//Set status to "poi" (Enter Points of Interest),
				//for use with overridden mouseRelease method.
				modeStatus = "Polygon";
				newFeatureName = null;
				currentPolygon = new Polygon(null);
				
				//Print to console.
				System.out.println("to: " + modeStatus);
		
				//Repaint the GUI.
				repaint();
			}
			
			//------------------------------------------
			
			if (arg0.getActionCommand() == "Load POIs"){

				//Show Open dialog
				int returnVal = fc.showOpenDialog(this);

				//Read array list of POIs from user-specified binary file.
		        if (returnVal == JFileChooser.APPROVE_OPTION) {
		            File file = fc.getSelectedFile();
		            poiList = op1.readFile(file);// This may need altering
		            
					System.out.println("");
					System.out.println("POIs loaded from data file:");
					System.out.println(file);
		        }
				//Repaint the GUI.
				repaint();
			}
			
			if (arg0.getActionCommand() == "Load Web POIs"){

				    poiList = op1.readFileWeb();
					System.out.println("");
					System.out.println("Web POIs loaded.");
					
		        }
				//Repaint the GUI.
				repaint();
			//}
			
			if (arg0.getActionCommand() == "Save POIs"){
				
				//Show Save dialog
				int returnVal = fc.showSaveDialog(this);
				
				//Write array list of POIs to user-specified binary file.
		        if (returnVal == JFileChooser.APPROVE_OPTION) {
		            File file = fc.getSelectedFile();
					op1.writeFile(poiList, file);// This may need altering
					System.out.println("");
					System.out.println("POIs saved to data file:");
					System.out.println(file);
		        }
				//Repaint the GUI.
				repaint();
			}		
			
			//------------------------------------------
			
			if (arg0.getActionCommand() == "Load Polylines"){

				//Show Open dialog
				int returnVal = fc.showOpenDialog(this);

				//Read array list of Polylines from user-specified binary file.
		        if (returnVal == JFileChooser.APPROVE_OPTION) {
		            File file = fc.getSelectedFile();
		            polyLineList = op2.readFile(file);// This may need altering
		            
					System.out.println("");
					System.out.println("Polylines loaded from data file:");
					System.out.println(file);
		        }
				//Repaint the GUI.
				repaint();
			}
			
			if (arg0.getActionCommand() == "Load Web Polylines"){

					polyLineList = op2.readFileWeb();
					System.out.println("");
					System.out.println("Web Polylines loaded.");
					
		        }
				//Repaint the GUI.
				repaint();
			//}
			
			if (arg0.getActionCommand() == "Save Polylines"){
				
				//Show Save dialog
				int returnVal = fc.showSaveDialog(this);
				
				//Write array list of PolyLines to user-specified binary file.
		        if (returnVal == JFileChooser.APPROVE_OPTION) {
		            File file = fc.getSelectedFile();
					op2.writeFile(polyLineList, file);
					System.out.println("");
					System.out.println("Polylines saved to data file:");
					System.out.println(file);
		        }
				//Repaint the GUI.
				repaint();
			}			
			
			//------------------------------------------
			
			if (arg0.getActionCommand() == "Load Polygons"){

				//Show Open dialog
				int returnVal = fc.showOpenDialog(this);

				//Read array list of Polygons from user-specified binary file.
		        if (returnVal == JFileChooser.APPROVE_OPTION) {
		            File file = fc.getSelectedFile();
		            polygonList = op3.readFile(file);
		            
					System.out.println("");
					System.out.println("Polygons loaded from data file:");
					System.out.println(file);
		        }
				//Repaint the GUI.
				repaint();
			}
			
			if (arg0.getActionCommand() == "Load Web Polygons"){

					polygonList = op3.readFileWeb();
					System.out.println("");
					System.out.println("Web Polygons loaded.");
					
		        }
				//Repaint the GUI.
				repaint();

			
			if (arg0.getActionCommand() == "Save Polygons"){
				
				//Show Save dialog
				int returnVal = fc.showSaveDialog(this);
				
				//Write array list of Polygons to user-specified binary file.
		        if (returnVal == JFileChooser.APPROVE_OPTION) {
		            File file = fc.getSelectedFile();
					op3.writeFile(polygonList, file);
					System.out.println("");
					System.out.println("Polygons saved to data file:");
					System.out.println(file);
		        }
				//Repaint the GUI.
				repaint();
			}
			
			
		} //End ACTIONS
		
			
			

		

	//====================================================================================
	//PAINT (VIEW)
	//====================================================================================


		/*
		 * Java takes care of calling this method. For this reason we had to define MinimalDrawingGUI 
		 * as a subclass of JPanel (line 14). You do not need to call the method by hand. If, however, you
		 * change data in your model, e.g., the PointBuffer, you will have to call repaint().
		 * 
		 */
		public void paintComponent(Graphics g) {
	        super.paintComponent(g);    // Paints all other stuff, e..g., background. (Is this defined in JPanel?).
	        
	        // Cast to a Graphics2D object to support affine transformations.
	        Graphics2D g2d = (Graphics2D) g;
	        
	        //Draw the background campus map.
	        g2d.drawImage(campus, 0, 0, this);	   
		       	        
			//------------------------------------------
			
	        //Draw POIs. 
	        if (poiList != null){
	        	
	        	//Draw POI Points.
	        	for (int i=0; i<poiList.size(); i++){
	        		g2d.setColor(Color.red);
	        		g2d.fillOval(
	        				(int) poiList.get(i).getPt().getX()-4,
	        				(int) poiList.get(i).getPt().getY()-4,
	        				(int) 2*4,
	        				(int) 2*4
	        				);
	        	}
	        }
	       
	        //Draw POI Labels, if the Digitized Path Points are inside the POI PointBuffer.
	        for (int dig = 0; dig < digList.size(); dig++){
	        	for (int poi = 0; poi < poiList.size(); poi++){
	        		if (poiList.get(poi).isInside(digList.get(dig))) {
	        			//Create font.
	        			Font fontBold = new Font ("Helvetica", Font.BOLD, 16);
	        			//Set font.
	        			g2d.setFont(fontBold);
	        			//Draw Label.
	        			g2d.drawString(
	        					poiList.get(poi).getLabel().toString(),
	        					(int) poiList.get(poi).getPt().getX() + 6,
	        					(int) poiList.get(poi).getPt().getY() + 6
	        					);
	        		}
	        	}
	        }
   	        
	        //------------------------------------------

	        //Draw PolyLines. 
	        if (polyLineList != null){

	        	//Draw PolyLine Points.
	        	for (int i=0; i<polyLineList.size(); i++){
	        		PolyLine tempPolyLine = polyLineList.get(i);
	        		for (int j=0; j<tempPolyLine.getPolypoints().size(); j++){
	        		g2d.setColor(Color.blue);
	        		g2d.fillOval(
	        				(int) tempPolyLine.getPolypoints().get(j).getPt().getX()-4,
	        				(int) tempPolyLine.getPolypoints().get(j).getPt().getY()-4,
	        				(int) 2*4,
	        				(int) 2*4
	        				);
	        		}
	        	}
	        }

	        //Draw PolyLine Labels, if the Digitized Path Points are inside the POI PointBuffer.
	        for (int dig = 0; dig < digList.size(); dig++){
	        	for (int i = 0; i < polyLineList.size(); i++){
	        		PolyLine tempPolyLine = polyLineList.get(i);
	        		for (int j=0; j<tempPolyLine.getPolypoints().size(); j++){
	        			if (tempPolyLine.getPolypoints().get(j).isInside(digList.get(dig))) {
	        				//Create font.
	        				Font fontBold = new Font ("Helvetica", Font.BOLD, 16);
	        				//Set font.
	        				g2d.setFont(fontBold);
	        				//Draw Label.
	        				g2d.drawString(
	        						tempPolyLine.getLabel().toString(),
	        						(int) tempPolyLine.getPolypoints().get(j).getPt().getX() + 6,
	        						(int) tempPolyLine.getPolypoints().get(j).getPt().getY() + 6
	        						);
	        			}
	        		}
	        	}
	        }
	        
        	//Draw PolyLine lines if more than one Point.
        	for(int i=0; i<polyLineList.size(); i++){
        		if (polyLineList.get(i).getPolypoints().size() > 1){
        			for (int j=0; j < polyLineList.get(i).getPolypoints().size()-1; j++){
        				g2d.drawLine(
        						(int) polyLineList.get(i).getPolypoints().get(j).getPt().getX(),
        						(int) polyLineList.get(i).getPolypoints().get(j).getPt().getY(),
        						(int) polyLineList.get(i).getPolypoints().get(j+1).getPt().getX(),
        						(int) polyLineList.get(i).getPolypoints().get(j+1).getPt().getY()
        						);
        			}
        		}        		
        	}


	        //------------------------------------------

	        //Draw Polygons. 
	        if (polygonList != null){

	        	//Draw Polygon Points.
	        	for (int i=0; i<polygonList.size(); i++){
	        		Polygon tempPolygon = polygonList.get(i);
	        		for (int j=0; j<tempPolygon.getPolypoints().size(); j++){
	        		g2d.setColor(Color.black);
	        		g2d.fillOval(
	        				(int) tempPolygon.getPolypoints().get(j).getPt().getX()-4,
	        				(int) tempPolygon.getPolypoints().get(j).getPt().getY()-4,
	        				(int) 2*4,
	        				(int) 2*4
	        				);
	        		}
	        	}
	        }

	        //Draw Polygon Labels, if the Digitized Path Points are inside the POI PointBuffer.
	        for (int dig = 0; dig < digList.size(); dig++){
	        	for (int i = 0; i < polygonList.size(); i++){
	        		Polygon tempPolygon = polygonList.get(i);
	        		for (int j=0; j<tempPolygon.getPolypoints().size(); j++){
	        			if (tempPolygon.getPolypoints().get(j).isInside(digList.get(dig))) {
	        				//Create font.
	        				Font fontBold = new Font ("Helvetica", Font.BOLD, 16);
	        				//Set font.
	        				g2d.setFont(fontBold);
	        				//Draw Label.
	        				g2d.drawString(
	        						tempPolygon.getLabel().toString(),
	        						(int) tempPolygon.getPolypoints().get(j).getPt().getX() + 6,
	        						(int) tempPolygon.getPolypoints().get(j).getPt().getY() + 6
	        						);
	        			}
	        		}
	        	}
	        }

        	//Draw Polygon lines if more than one Point.
        	for(int i = 0; i<polygonList.size(); i++){
        		if (polygonList.get(i).getPolypoints().size() > 1){
        			for (int j=0; j < polygonList.get(i).getPolypoints().size()-1; j++){
        				g2d.drawLine(
        						(int) polygonList.get(i).getPolypoints().get(j).getPt().getX(),
        						(int) polygonList.get(i).getPolypoints().get(j).getPt().getY(),
        						(int) polygonList.get(i).getPolypoints().get(j+1).getPt().getX(),
        						(int) polygonList.get(i).getPolypoints().get(j+1).getPt().getY()
        						);
        			}
        		}  
        	}	
        		
        	//Fill previously defined polygons with transparent red
        	for(int i = 0; i<polygonList.size()-1; i++){	
        		if (polygonList.get(i).getPolypoints().size() > 1)
        		{
        			
        			//have to bust open the polygon since it's not the awt "Polygon" class
        			//so it can be fed into g2d.fillPolygon
        			int [] xPoints = new int[polygonList.get(i).getPolypoints().size()-1];
            		int [] yPoints = new int[polygonList.get(i).getPolypoints().size()-1];
            		int npoints;
        			npoints = (polygonList.get(i).getPolypoints().size())-1;
        			for (int j=0; j < polygonList.get(i).getPolypoints().size()-1; j++){
        				
        				xPoints[j] = (int) polygonList.get(i).getPolypoints().get(j).getPt().getX();
        				yPoints[j] = (int) polygonList.get(i).getPolypoints().get(j).getPt().getY();
        				
        			}
        			Color color = new Color(1,0,0,alpha); //Red
        			g2d.setPaint(color);
        			g2d.fillPolygon(xPoints, yPoints, npoints);       		
        		}       		
        	}
        	
        	//Only fill polygon that is currently being created when complete.
        	if (polygonList.size() > 0){ 
        		if(polygonList.get(polygonList.size()-1).getPolypoints().size() > 1
        		& polygonList.get(polygonList.size()-1).isPolygon(polygonList.get(polygonList.size()-1))
        		){
        			//have to bust open the polygon since it's not the awt "Polygon" class
        			//so it can be fed into g2d.fillPolygon
        			int [] xPoints = new int[polygonList.get(polygonList.size()-1).getPolypoints().size()-1];
        			int [] yPoints = new int[polygonList.get(polygonList.size()-1).getPolypoints().size()-1];
        			int npoints;
        			npoints = (polygonList.get(polygonList.size()-1).getPolypoints().size())-1;
        			for (int j=0; j < polygonList.get(polygonList.size()-1).getPolypoints().size()-1; j++){

        				xPoints[j] = (int) polygonList.get(polygonList.size()-1).getPolypoints().get(j).getPt().getX();
        				yPoints[j] = (int) polygonList.get(polygonList.size()-1).getPolypoints().get(j).getPt().getY();

        			}
        			Color color = new Color(1,0,0,alpha); //Red
        			g2d.setPaint(color);
        			g2d.fillPolygon(xPoints, yPoints, npoints);       		
        		} 
        	}
        	       	
	        
		} //End PAINT

		
		

				
	//====================================================================================
	//MAIN Program (embedded) (MODEL)
	//====================================================================================

		public static void main(String[] args) throws InterruptedException, IOException {

			System.out.println("Mike and Bo's Homework #10");
			System.out.println("==========================");
			System.out.println("");
			System.out.println("Notes:");
			System.out.println("");
			System.out.println("1) To complete a point-of-interest (POI),");
			System.out.println("   after digitizing the point location,");
			System.out.println("   specify the name in the dialog box.");
			System.out.println("   If no additional POIs are desired,");
			System.out.println("   dismiss the POI naming dialog.");
			System.out.println("");
			System.out.println("2) To complete a polyline, right-click.");
			System.out.println("   The polyline mode will contine");
			System.out.println("   and the first point of the next polyline");
			System.out.println("   will be the location of the right-click.");
			System.out.println("   If no additional polylines are desired,");
			System.out.println("   dismiss the polyline naming dialog.");
			System.out.println("");
			System.out.println("3) To complete a polygon, click near start point.");
			System.out.println("   The polygon mode will contine.");
			System.out.println("   If no additional polygons are desired,");
			System.out.println("   dismiss the polygon naming dialog.");
			System.out.println("   The Polyline Closing Snap Distance can be");
			System.out.println("   specified through an 'Edit' menu item.");
			System.out.println("");
			System.out.println("4) POI or polyline/polygon vertices");
			System.out.println("   can be moved by first selecting the");
			System.out.println("   appropriate 'Edit' menu item.");
			System.out.println("   Then, hovering the cursor near a corresponding");
			System.out.println("   corresponding point will change the cursor.");
			System.out.println("   Clicking, dragging, and releasing will move the point.");
			System.out.println("");
			System.out.println("5) POI or polyline/polygon vertices");
			System.out.println("   can be labeled from the 'Inquiry' menu.");
			System.out.println("   The first label may take some time.");
			System.out.println("");
			System.out.println("6) A full listing of objects can be printed");
			System.out.println("   to the console from the 'Inquiry' menu.");
			System.out.println("");
			System.out.println("7) The Load Web, Load Local, Save Local commands");
			System.out.println("   import and export binary (.bif) files.");
			System.out.println("");
			System.out.println("8) The Load Web commands work if the package is");
			System.out.println("   named the same as when the objects were saved.");
			System.out.println("   (e.g. 'Week10').");
			System.out.println("");
			System.out.println("*) Thanks for all the great ideas and guidance, Jano!");
			System.out.println("   Have a great Spring Break!");
			System.out.println("");
			System.out.println("==========================");
			

			//==================================================		
			//Create instance of MapMainProg class and add components.
			
			MapMainProg gui = new MapMainProg();
			
			//Add mouse listener and mouse motion listener
			gui.addMouseListener(gui);
			gui.addMouseMotionListener(gui);


			//Load the image (this time we do not handle the exception but throw it somewhere else ;-))
			campus = ImageIO.read(new File("C:\\java\\campus.png"));
			
			//adding menus
			JMenuBar menuBar = new JMenuBar();
			
			JMenu LoadWebMenu = new JMenu("Load Web");
			JMenu LoadLocalMenu = new JMenu("Load Local");
			JMenu SaveLocalMenu = new JMenu("Save Local");
			JMenu editMenu = new JMenu("Edit");
			JMenu inquiryMenu = new JMenu("Inquiry");
			
			//adding menus items
			JMenuItem LoadPOIMenuItem = new JMenuItem("Load POIs");
			JMenuItem LoadPOIWebMenuItem = new JMenuItem("Load Web POIs");
			JMenuItem SavePOIMenuItem = new JMenuItem("Save POIs");	
			
			JMenuItem LoadPolyLineMenuItem = new JMenuItem("Load Polylines");
			JMenuItem LoadPolyLineWebMenuItem = new JMenuItem("Load Web Polylines");
			JMenuItem SavePolyLineMenuItem = new JMenuItem("Save Polylines");	
			
			JMenuItem LoadPolygonMenuItem = new JMenuItem("Load Polygons");
			JMenuItem LoadPolygonWebMenuItem = new JMenuItem("Load Web Polygons");
			JMenuItem SavePolygonMenuItem = new JMenuItem("Save Polygons");		
			
			JMenuItem poiMenuItem = new JMenuItem("Create/Move POIs");
			JMenuItem polyLineMenuItem = new JMenuItem("Create/Move Polyline Vertices");
			JMenuItem polygonMenuItem = new JMenuItem("Create/Move Polygon Vertices");
			JMenuItem polygonSnapMenuItem = new JMenuItem("Polygon Closing Snap Distance");
			
			JMenuItem digMenuItem = new JMenuItem("Label POI or Vertex");
			JMenuItem listMenuItem = new JMenuItem("List all objects");
			
			//JMenuItem digMenuItem = new JMenuItem("Digitize Path");
			
			//add menu to menubar
			menuBar.add(LoadWebMenu);
			menuBar.add(LoadLocalMenu);
			menuBar.add(SaveLocalMenu);
			menuBar.add(editMenu);
			menuBar.add(inquiryMenu);
			
			//add items to menus
			LoadWebMenu.add(LoadPOIWebMenuItem);
			LoadWebMenu.add(LoadPolyLineWebMenuItem);
			LoadWebMenu.add(LoadPolygonWebMenuItem);
			
			LoadLocalMenu.add(LoadPOIMenuItem);
			LoadLocalMenu.add(LoadPolyLineMenuItem);
			LoadLocalMenu.add(LoadPolygonMenuItem);
			
			SaveLocalMenu.add(SavePOIMenuItem);
			SaveLocalMenu.add(SavePolyLineMenuItem);
			SaveLocalMenu.add(SavePolygonMenuItem);
			
			editMenu.add(poiMenuItem);
			editMenu.add(polyLineMenuItem);
			editMenu.add(polygonMenuItem);
			editMenu.add(polygonSnapMenuItem);
			
			inquiryMenu.add(digMenuItem);
			inquiryMenu.add(listMenuItem);
			
				
			//adding action listeners for menu items
			LoadPOIMenuItem.addActionListener(gui);
			LoadPOIWebMenuItem.addActionListener(gui);
			SavePOIMenuItem.addActionListener(gui);
			
			LoadPolyLineMenuItem.addActionListener(gui);
			LoadPolyLineWebMenuItem.addActionListener(gui);
			SavePolyLineMenuItem.addActionListener(gui);
			
			LoadPolygonMenuItem.addActionListener(gui);
			LoadPolygonWebMenuItem.addActionListener(gui);
			SavePolygonMenuItem.addActionListener(gui);
			
			poiMenuItem.addActionListener(gui);
			polyLineMenuItem.addActionListener(gui);
			polygonMenuItem.addActionListener(gui);
			polygonSnapMenuItem.addActionListener(gui);
			
			digMenuItem.addActionListener(gui);
			listMenuItem.addActionListener(gui);
			
			//===========================
			//Default GUI settings (begin)
			//Frame size is still hard-coded with setPreferredSize().

			//Create JFrame to place other components such as panels or buttons within.
			JFrame frame = new JFrame("Campus Map: Points of Interest and Digitize Path");

			//Add an instance of the MinimalDrawingGUI to the frame.
			frame.add(gui);
			
			//Set the size, arrange components, and display the frame.
			frame.pack();
			frame.setVisible(true);
			
			//Exit on close.
			frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
			
			//set menu in frame
			frame.setJMenuBar(menuBar);

			//Default GUI settings (end)
			//==========================
						
			
		} //End MAIN


		
		
	//====================================================================================
	//METHODS for MapMainProg class
	//====================================================================================	
	    
		//Override for the mouseReleased method.
		@Override
		public void mouseReleased(MouseEvent mUp) {
			
			//Get the mouse coordinates.
			mouseX =  mUp.getX();
			mouseY =  mUp.getY();
			
			//Actions if the "Label POI or Vertex" button was pressed and the mouse button was released.
			if (modeStatus == "dig"){
				
				//Create Point from mouse coordinates.
				Point pnt = new Point((double) mouseX, (double) mouseY);
				
				//Add Point to the "Inquiry" ArrayList.
				digList.add(pnt);
				
			}
			
			//Actions if the POI menu item was pressed and the mouse button was released.
			//But only if it's not a crosshair cursor
			if (modeStatus == "poi" & cursorStatus == 1){
				
				//Dialog box for user-specified Point of Interest name.
				newFeatureName = (String)JOptionPane.showInputDialog(
				                    null,
				                    "Enter a name for your Point of Interest.",
				                    "Point of Interest",
				                    JOptionPane.PLAIN_MESSAGE,
				                    null,
				                    null,
				                    "POI " + (poiList.size()+1));
				
				
				//Create Point from mouse coordinates if string is not empty				
				if (newFeatureName != null){
					Point pnt = new Point((double) mouseX, (double) mouseY);

					//Create POI from Point, hard-coded PointBuffer radius, Label.
					POI poi = new POI(pnt, (double) 8, newFeatureName);

					//Add Point to the "Enter Point of Interest" ArrayList
					poiList.add(poi);

					//Print to console.
					System.out.println("");
					System.out.println("Points of Interest coordinates and name:");
					for (int i=0; i < poiList.size(); i++){
						System.out.println(poiList.get(i).getPt() + "   " + poiList.get(i).getLabel());	
						op1.setPoiListin(poiList);
					}				
					//if inDrag was set because you were dragging a poi, it now is unset
					inDrag = false;					
				}
				
			}	
			
			//Actions if the PolyLine menu item was pressed and the mouse button was released.
			//But only if it's not a crosshair cursor
			if (modeStatus == "PolyLine" & cursorStatus == 1){
				
				//Dialog box for user-specified Polyline name.
				if (newFeatureName == null){
					newFeatureName = (String)JOptionPane.showInputDialog(
				                    null,
				                    "Enter a name for your Polyline.",
				                    "Polyline",
				                    JOptionPane.PLAIN_MESSAGE,
				                    null,
				                    null,
				                    "Polyline " + (polyLineList.size()+1));
					
					if (newFeatureName != null){
						currentPolyline = new PolyLine(null);
						polyLineList.add(currentPolyline);
						polyLineList.get(polyLineList.size()-1).setLabel(newFeatureName);				
					}
				}
				

				//Create PolyLine from mouse coordinates if string is not empty				
				if (newFeatureName != null){
										
					Point pnt = new Point((double) mouseX, (double) mouseY);

					//Create POI from Point, hard-coded PointBuffer radius, Label.
					POI poi = new POI(pnt, (double) 8, null);

					currentPolyline.add(poi);

					//if inDrag was set because you were dragging a poi, it now is unset
					inDrag = false;					
				}							
			}
			

			//Actions if the Polygon menu item was pressed and the mouse button was released.
			//But only if it's not a crosshair cursor
			if (modeStatus == "Polygon" & cursorStatus == 1){

					//Dialog box for user-specified Polygon name.
					if (newFeatureName == null){
						newFeatureName = (String)JOptionPane.showInputDialog(
								null,
								"Enter a name for your Polygon.",
								"Polygon",
								JOptionPane.PLAIN_MESSAGE,
								null,
								null,
								"Polygon " + (polygonList.size()+1));
						
						if (newFeatureName != null){
							currentPolygon = new Polygon(null);
							polygonList.add(currentPolygon);
							polygonList.get(polygonList.size()-1).setLabel(newFeatureName);
						}
					}


					//Create Polygon from mouse coordinates if string is not empty				
					if (newFeatureName != null){
						Point pnt = new Point((double) mouseX, (double) mouseY);

						//Create POI from Point, hard-coded PointBuffer radius, Label.
						POI poi = new POI(pnt, (double) 8, null);

						currentPolygon.add(poi);

						//if inDrag was set because you were dragging a poi, it now is unset
						inDrag = false;					
					}
					
					if (
						(polygonList.get(polygonList.size()-1).getPolypoints().size() >1)
						&
						polygonList.get(polygonList.size()-1).getPolypoints().get(polygonList.get(polygonList.size()-1).getPolypoints().size()-1).getPt().getDistance(polygonList.get(polygonList.size()-1).getPolypoints().get(0).getPt()) <= polygonSnapDist
						)
						
					{
						polygonList.get(polygonList.size()-1).getPolypoints().get(polygonList.get(polygonList.size()-1).getPolypoints().size()-1).setPt(polygonList.get(polygonList.size()-1).getPolypoints().get(0).getPt());
						polygonList.set(polygonList.size()-1, polygonList.get(polygonList.size()-1));
						
						//indicator that we're now going to be dealing with a new polygon
						newFeatureName = null;	
					}
			}
			repaint();			
		}
		
		
		@Override
		public void mouseClicked(MouseEvent arg0) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mouseEntered(MouseEvent arg0) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mouseExited(MouseEvent arg0) {
			// TODO Auto-generated method stub
			
		}

		@Override
		public void mousePressed(MouseEvent mousePress) {
			
			//if mode status is poi mode then we'll get the coords of the press
			if (modeStatus == "poi" & poiList.size() > 0){
				Point p = new Point(mousePress.getX(),mousePress.getY());
				
				//setting an index so we know which poi is going to get dragged
				for (int i=0; i <= poiList.size()-1; i++){
					if (poiList.get(i).isInside(p)){
						  poiIndex = i;
						break;
					}
				}
				//set flag that dragging might happen (used in the mouseDragged event) 
				inDrag = true;
			}
			
			
			
			if (modeStatus == "PolyLine" & polyLineList.size() > 0){
				if (mousePress.isMetaDown()){
					newFeatureName = null;
					System.out.println("");
					System.out.println("A Polyline has been completed.");
				}	
				else{
				
				Point p = new Point(mousePress.getX(),mousePress.getY());

				//setting an index so we know which poi is going to get dragged
				for (int i=0; i < polyLineList.size(); i++){
					for (int j=0; j < polyLineList.get(i).getPolypoints().size(); j++){
						if (polyLineList.get(i).getPolypoints().get(j).isInside(p)){
							polyLineIndex = i;
							polyLinePoiIndex = j;
							break;
						}						
					}

				}
				//set flag that dragging might happen (used in the mouseDragged event) 
				inDrag = true;				
				}
			}
			
			
			
			//cursorStatus of 3 means it's time to drag a Polygon
			if (cursorStatus == 3 & polygonList.size() > 0){
				Point p = new Point(mousePress.getX(),mousePress.getY());

				//setting an index so we know which poi is going to get dragged
				for (int i=0; i < polygonList.size(); i++){
					for (int j=0; j < polygonList.get(i).getPolypoints().size(); j++){
						if (polygonList.get(i).getPolypoints().get(j).isInside(p)){
							polygonIndex = i;
							polygonPoiIndex = j;
							break;
						}						
					}
				}
				//set flag that dragging might happen (used in the mouseDragged event) 
				inDrag = true;
			}				
		}


		@Override
		public void mouseDragged(MouseEvent e) {
			//if statement so that the poi isn't moved during digitization
			//poi mode
			if (modeStatus=="poi" & cursorStatus == 4){

				Point p = new Point(e.getX(),e.getY());


				curX = (int) p.getX();
				curY = (int) p.getY();
				if (inDrag) {
					poiList.get(poiIndex).getPt().setX(curX);
					poiList.get(poiIndex).getPt().setY(curY);

					//update file with new location
					op1.setPoiListin(poiList);	
					
					repaint();
				}
			}
			
			
			//PolyLine mode
			if (modeStatus=="PolyLine" & cursorStatus == 2){

				Point p = new Point(e.getX(),e.getY());

				curX = (int) p.getX();
				curY = (int) p.getY();
				if (inDrag) {
					polyLineList.get(polyLineIndex).getPolypoints().get(polyLinePoiIndex).getPt().setX(curX);
					polyLineList.get(polyLineIndex).getPolypoints().get(polyLinePoiIndex).getPt().setY(curY);

					//update file with new location
					op2.setPolyLineListin(polyLineList);	
					
					repaint();
				}
			}
			
			
			//Polygon mode
			if (modeStatus=="Polygon" & cursorStatus == 3){

				Point p = new Point(e.getX(),e.getY());

				curX = (int) p.getX();
				curY = (int) p.getY();
			
				
				if (inDrag) {
					polygonList.get(polygonIndex).getPolypoints().get(polygonPoiIndex).getPt().setX(curX);
					polygonList.get(polygonIndex).getPolypoints().get(polygonPoiIndex).getPt().setY(curY);

					//update file with new location
					op3.setPolygonListin(polygonList);	
					
					repaint();
				}
			}
						
		}
			
			
		




		@Override
		
		//defining the cursor type based on location compared to POI
		public void mouseMoved(MouseEvent evt) {
			
			Point p = new Point(evt.getX(),evt.getY());
			
			
			//Every movement initially resets the cursor to default but 
			//then it can change to 2,3, or 4 depending on whose buffer it's inside of			
			setCursor(Cursor.getDefaultCursor());
			cursorStatus=1;			
		
			for (int i=0; i < poiList.size(); i++){
				if (poiList.get(i).isInside(p)){
					setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
					//cursorStatus will drive what the user is able to do when clicking
					cursorStatus=4;  //4 is specific to poi-moving mode
					break;
				}				
			}
		  
		  
		  
			for (int i=0; i < polyLineList.size(); i++){
				for (int j=0; j < polyLineList.get(i).getPolypoints().size(); j++){				  
					if (polyLineList.get(i).getPolypoints().get(j).isInside(p)){
						setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
						//cursorStatus will drive what the user is able to do when clicking
						cursorStatus=2;
						break;
					}					
				}	
				//need to bust out of outer loop too
				if (cursorStatus == 2){break;};
			}
		  
		  		  
			for (int i=0; i < polygonList.size(); i++){
				for (int j=0; j < polygonList.get(i).getPolypoints().size(); j++){				  
					if (polygonList.get(i).getPolypoints().get(j).isInside(p)){
						setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
						//cursorStatus will drive what the user is able to do when clicking
						cursorStatus=3;
						break;
					}				
				}		
				//need to bust out of outer loop too
				if (cursorStatus == 3){break;};
			}		    
		}
		


		//Getters and Setters for MapMainProg class
		
		public Point getPnt() {
			return pnt;
		}

		public void setPnt(Point pnt) {
			this.pnt = pnt;
		}
		
		public int getMouseX() {
			return mouseX;
		}

		public void setMouseX(int mouseX) {
			this.mouseX = mouseX;
		}

		public int getMouseY() {
			return mouseY;
		}

		public void setMouseY(int mouseY) {
			this.mouseY = mouseY;
		}


	  //End METHODS
		
			
	} //End MapMainProg CLASS



